//
//  CountdownButton.swift
//  LoginModule
//
//  Created by xianquan on 2024/1/12.
//

import UIKit

public class CountdownButton: UIButton {
    
    private let totalTime = 60
    //一分钟倒计时
    private lazy var time = totalTime
    //进入后台时存储当前时间
    private var becomeDeathTime: Date!
    //进入前台时存储当前时间
    private var becomeActiveTime: Date!
    //GCD Timer
    private var timer: DispatchSourceTimer?
    
    public var usage: UsageScenario = .authCode
    
    public var isCountdowning: Bool {
        return time != totalTime
    }
    
    public var complete: () -> () = {}

    //添加通知
    private func addNotification() {
        
        //注册进入前台的通知
        NotificationCenter.default.addObserver(self, selector: #selector(becomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
        //注册进入后台的通知
        NotificationCenter.default.addObserver(self, selector: #selector(becomeDeath), name: UIApplication.willResignActiveNotification, object: nil)
    }
    //移除通知
    private func removeNotification() {
        NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
        NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil)
    }
    
    @objc private func becomeActive() {
        //存储进入前台时的时间
        becomeActiveTime = Date()
        if becomeDeathTime != nil {
            //计算出退出后台到进入前台的时间差
            let difference: Int = Int(becomeActiveTime.timeIntervalSince(becomeDeathTime))
            //DispatchSourceTimer退出后台时是暂停的，返回前台时，需要减去时间差
            time = time - difference
        }
    }
    
    @objc private func becomeDeath() {
        //存储进入后台时的时间
        becomeDeathTime = Date()
    }
    
    //计时器**和注销的方法
    public func beginCountdown() {
        if timer != nil {
            XWLog(value: "倒计时已开始")
            return
        }
        //添加监控退出到后台以及进入前台的通知
        addNotification()
        //倒计时的时候当前按钮不可点击，同时可以为状态disabled的按钮设置灰色的背景图片
        isEnabled = false
        //子线程创建计时器
        let timer = DispatchSource.makeTimerSource(flags: .init(rawValue: 0), queue: DispatchQueue.global())
        self.timer = timer
        //dealine:开始执行时间 repeating:重复时间
        timer.schedule(deadline: .now(), repeating: .milliseconds(1000))
        //添加计时器的事件
        timer.setEventHandler { [weak self] in
            guard let self = self else {return}
            time = time - 1
            if time < 0 {
                //注销计时器
                timer.cancel()
                //主线程更新UI
                DispatchQueue.main.async {[weak self] in
                    guard let self = self else {return}
                    isEnabled = true
                    setAttributedTitle(usage.restartText, for: .normal)
                    time = totalTime
                    complete()
                    self.timer = nil
                    //移除通知
                    removeNotification()
                }
                return
            }
            
            DispatchQueue.main.async {[weak self] in
                guard let self = self else {return}
                setAttributedTitle(usage.countdownText(time: time), for: .normal)
            }
        }
        //计时器**
        timer.activate()
    }
    
    func reset(){
        if let timer = timer {
            timer.cancel()
            self.timer = nil
            removeNotification()
            time = totalTime
            isEnabled = true
            setAttributedTitle(usage.restartText, for: .normal)
        }
    }
    
    func stop(){
        if let timer = timer {
            timer.cancel()
            removeNotification()
            self.timer = nil
        }
    }
    
    deinit {
        stop()
        XWLog(value: "倒计时按钮销毁了")
    }
}


public extension CountdownButton {
    enum UsageScenario {
        case authCode
        case password
        
        var restartText: NSAttributedString{
            switch self {
            case .authCode:
                let att = NSMutableAttributedString(string: "重新发送")
                att.yy_font = .systemFont(ofSize: adapt(14), weight: .medium)
                att.yy_color = .selectedColor
                return att
            case .password:
                let att = NSMutableAttributedString(string: "重新获取")
                att.yy_font = .systemFont(ofSize: adapt(18), weight: .medium)
                att.yy_color = .white
                return att
            }
        }
        
        func countdownText(time: Int) -> NSAttributedString{
            switch self {
            case .authCode:
                let att = NSMutableAttributedString(string: "\(time)秒后再次发送")
                att.yy_font = .systemFont(ofSize: adapt(14), weight: .medium)
                att.yy_color = .blackb0
                return att
            case .password:
                let att = NSMutableAttributedString(string: "\(time)秒")
                att.yy_font = .systemFont(ofSize: adapt(14), weight: .medium)
                att.yy_color = .selectedColor
                return att
            }
        }
        
        
    }
}
